package com.info33.platform.common.api;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.info33.platform.common.mvc.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.FileReader;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 调用 三方 api 工具包
 *
 * @author debj
 * @version 1.0
 * @date 2021/8/19 16:30
 */
@Slf4j
@Component
public class Apis {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 根据城市编码获取气象预警
     *
     * @param code 城市编码
     * @return jsonObject
     */
    public JSONObject getWeatherWarnByCode(String code) {
        try {
            JSONObject object = new JSONObject(HttpUtil.get("https://devapi.qweather.com/v7/warning/now?key=ffd8b11a133941d4a3be34d125a31dea&location=" + code));
            if (200 == object.getInt("code")) {
                return object;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONObject();
    }


    /**
     * 根据地址获取对应经纬度
     *
     * @param address 北京市海淀区上地十街10号
     * @return -
     */
    public Result<Point> getLocation(String address) {
        try {
            Map<String, String> paramsMap = new LinkedHashMap<>();
            paramsMap.put("address", address);
            paramsMap.put("ak", "o3z6zHtXj2RA9aNywFObfMlT7XfW0oQK");
            paramsMap.put("output", "json");

            String tempStr = URLEncoder.encode("/geocoding/v3/?" + HttpUtil.toParams(paramsMap) + "ZOtRIZTgHni7Oib1v8R8ay5DaReNKwYt", "UTF-8");

            StringBuilder sb = new StringBuilder();
            for (byte b : MessageDigest.getInstance("MD5").digest(tempStr.getBytes())) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);
            }
            paramsMap.put("sn", sb.toString());
            JSONObject jsonObject = new JSONObject(HttpUtil.get("https://api.map.baidu.com/geocoding/v3/?" + HttpUtil.toParams(paramsMap)));
            log.info(jsonObject.toString());
            if (jsonObject.getInt("status").equals(0)) {
                JSONObject location = jsonObject.getJSONObject("result").getJSONObject("location");
                return Result.ok("百度 api 支持", new Point(location.getDouble("lat"), location.getDouble("lng")));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.error();
    }


    /**
     * 获取天气信息
     *
     * @return 异常则为 null
     * @deprecated 线上调用会直接返回 null
     */
    @Deprecated
    public JSONObject getWeather(String cityName) {
        StringBuilder sb = new StringBuilder();
        try (FileReader fr = new FileReader(new ClassPathResource("static/citycode.json").getFile())) {
            char[] ch = new char[1024];
            int len;
            while ((len = fr.read(ch)) != -1) {
                sb.append(ch, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        for (Object l : new JSONArray(sb.toString())) {
            JSONObject jsonObject = new JSONObject(l.toString());
            String cityCode;
            if (jsonObject.getStr("city_name").contains(cityName) || cityName.contains(jsonObject.getStr("city_name"))) {
                cityCode = jsonObject.getStr("city_code");
                if (StringUtils.isNotBlank(cityCode)) {
                    return getWeatherByCode(cityCode);
                }
            }
        }
        return null;
    }

    /**
     * 根据城市编码获取对应气象信息
     *
     * @param code 城市编码
     * @return jsonObject
     */
    public JSONObject getWeatherByCode(String code) {
        // 从缓存中取值
        String cacheKey = "weatherInfo:";
        Object weather = redisTemplate.opsForValue().get(cacheKey + code);
        if (!ObjectUtils.isEmpty(weather)) {
            return new JSONObject(weather);
        }
        // 你需要尽量避免此 api 的调用
        JSONObject data_nowjason = new JSONObject(HttpUtil.get("http://t.weather.itboy.net/api/weather/city/" + code));
        List<JSONObject> forecast = data_nowjason.getJSONObject("data").getJSONArray("forecast").toList(JSONObject.class);
        forecast.forEach(e -> {
            String high = e.getStr("high");
            String low = e.getStr("low");
            String regEx = "[^0-9]";
            Pattern p = Pattern.compile(regEx);
            Matcher newHigh = p.matcher(high);
            Matcher newLow = p.matcher(low);
            e.putOpt("high", newHigh.replaceAll("").trim());
            e.putOpt("low", newLow.replaceAll("").trim());
        });
        redisTemplate.opsForValue().set(cacheKey + code, data_nowjason, 3, TimeUnit.HOURS);
        return data_nowjason;
    }


    /**
     * 根据经纬度获取地址
     *
     * @param point 经纬度
     * @return 地址
     */
    public Result<String> getAddressByPoint(Point point) {
        try {
            Map<String, String> paramsMap = new LinkedHashMap<>();
            paramsMap.put("ak", "o3z6zHtXj2RA9aNywFObfMlT7XfW0oQK");
            paramsMap.put("location", point.getX() + "," + point.getY());
            paramsMap.put("output", "json");
            paramsMap.put("radius", "500");

            // 对上面wholeStr再作utf8编码
            String tempStr = URLEncoder.encode("/reverse_geocoding/v3/?" + HttpUtil.toParams(paramsMap) + "ZOtRIZTgHni7Oib1v8R8ay5DaReNKwYt", "UTF-8");

            StringBuilder sb = new StringBuilder();
            for (byte b : MessageDigest.getInstance("MD5").digest(tempStr.getBytes())) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);
            }
            paramsMap.put("sn", sb.toString());
            JSONObject jsonObject = new JSONObject(HttpUtil.get("https://api.map.baidu.com/reverse_geocoding/v3/?" + HttpUtil.toParams(paramsMap)));
            log.info(jsonObject.toString());
            if (jsonObject.getInt("status").equals(0)) {
                return Result.ok("百度 api 支持", jsonObject.getJSONObject("result").getStr("formatted_address"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.error();
    }

}
